#include <crt_list.h>

void _list_init (struct _list_s *self)
{
    self->first = NULL;
    self->last = NULL;
}

void _list_term (struct _list_s *self)
{
	c_assert(self->first == NULL);
	c_assert(self->last == NULL);
}

int _list_empty (struct _list_s *self)
{
    return self->first ? 0 : 1;
}

struct _list_item *_list_begin (struct _list_s *self)
{
    return self->first;
}

struct _list_item *_list_end (struct _list_s *self)
{
    return NULL;
}

struct _list_item *_list_prev (struct _list_s *self,
    struct _list_item *it)
{
    if (!it)
        return self->last;
	rc_assert(it->prev != _LIST_NOTINLIST,NULL);
    return it->prev;
}

struct _list_item *_list_next (_unused struct _list_s *self,
    struct _list_item *it)
{
	rc_assert(it->next != _LIST_NOTINLIST,NULL);
    return it->next;
}

void _list_insert (struct _list_s *self, struct _list_item *item,
    struct _list_item *it)
{
	c_assert(!_list_item_isinlist (item));

    item->prev = it ? it->prev : self->last;
    item->next = it;
    if (item->prev)
        item->prev->next = item;
    if (item->next)
        item->next->prev = item;
    if (!self->first || self->first == it)
        self->first = item;
    if (!it)
        self->last = item;
}

struct _list_item *_list_erase (struct _list_s *self,
    struct _list_item *item)
{
    struct _list_item *next;

	rc_assert(_list_item_isinlist (item),NULL);

    if (item->prev)
        item->prev->next = item->next;
    else
        self->first = item->next;
    if (item->next)
        item->next->prev = item->prev;
    else
        self->last = item->prev;

    next = item->next;

    item->prev = _LIST_NOTINLIST;
    item->next = _LIST_NOTINLIST;

    return next;
}

void _list_item_init (struct _list_item *self)
{
    self->prev = _LIST_NOTINLIST;
    self->next = _LIST_NOTINLIST;
}

void _list_item_term (struct _list_item *self)
{
	c_assert(!_list_item_isinlist (self));
}

int _list_item_isinlist (struct _list_item *self)
{
    return self->prev == _LIST_NOTINLIST ? 0 : 1;
}

